#include "stdafx.h"
//-------------------------------------------------------------------------------------------------
//ImageObject.cpp  - Behaviour and data of an Image Property        
//-------------------------------------------------------------------------------------------------
//FreeBSD License
//Copyright 2011 Will Stott All rights reserved.
//
//Redistribution and use in source and binary forms, with or without modification, are
//permitted provided that the following conditions are met:
//
//   1. Redistributions of source code must retain the above copyright notice, this list of
//      conditions and the following disclaimer.
//
//   2. Redistributions in binary form must reproduce the above copyright notice, this list
//      of conditions and the following disclaimer in the documentation and/or other materials
//      provided with the distribution.
//
//THIS SOFTWARE IS PROVIDED BY Will Stott ``AS IS'' AND ANY EXPRESS OR IMPLIED
//WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
//FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Will Stott OR
//CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
//SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
//ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
//ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//The views and conclusions contained in the software and documentation are those of the
//authors and should not be interpreted as representing official policies, either expressed
//or implied, of Will Stott.
//
//----Authors--------------------------------------------------------------------------------------
//created by: will.stott@ucl.ac.uk Feb 2011
//
//----Comments-------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------

#include <sstream>
#include <string>
#include "ImageDataset.h"
#include "ImageObject.h"
#include "PtShape.h"
#include "PtShapeType.h"
#include "PtAnnotateShape.h"
#include "PtAnnotateShapeType.h"
#include "EllipseShape.h"
#include "EllipseShapeType.h"
#include "ImageProps.h"


ImageObject::ImageObject(void) :
	_pImageObjectType('\0'),
	_DisplayId(0),
	_DisplayName(""),
	_timestampStr("")
{
	 
}

ImageObject::ImageObject(ImageObjectType *pObjType) :
	_pImageObjectType(pObjType),
	_DisplayId(0),
	_DisplayName(""),
	_timestampStr("")
{
	CreateImageObjectProperties();
}

ImageObject::~ImageObject(void)
{
	ClearAllImageObjectProperties();
}

ImageObject *ImageObject::Create(ImageObjectType *pObjType, ImageProps *pImageProps)
{
	ImageObject *rc = '\0';

	if ((pImageProps != '\0') && (pObjType != '\0'))
	{
		const char *ObjectTypeName = pObjType->GetName();
		if (ObjectTypeName != '\0')
		{
			if ( pImageProps->CanCreateExpertImageObject(pObjType) )
			{
				std::string baseClassName(pObjType->GetBaseClassName());

				if (baseClassName == PtShapeType::baseClassName)
					rc = new PtShape(pObjType);
				else if (baseClassName == EllipseShapeType::baseClassName)
					rc = new EllipseShape(pObjType);	
				else if (baseClassName == PtAnnotateShapeType::baseClassName)
					rc = new PtAnnotateShape(pObjType);	

				if (rc != '\0' )
				{
					if (pImageProps->IncExpertObjsCreated(ObjectTypeName) == -1)
					{
						assert(pImageProps->DecExpertObjsCreated(ObjectTypeName) != -1);
						delete rc;
						rc = '\0';
					}
					else
					{
						int DisplayID = pImageProps->GetImageObjectCnt() + 1;
						if (rc->SetName(DisplayID) == false)
						{
							assert(pImageProps->DecExpertObjsCreated(ObjectTypeName) != -1);
							delete rc;
							rc = '\0';
						}
					}
				}
			}
		}
	}
	return rc;
}

ImageProp  *ImageObject::GetProperty(const char *Name)
{
	ImageProp  *rc = '\0';

	if (Name != '\0')
	{
		size_t cnt = _imageObjectProperties.size();
		if (cnt > 0 )
		{
			for (size_t x = 0; x < cnt; x++)
			{
				std::string imagePropName = Name;
				if (imagePropName == _imageObjectProperties[x]->GetPropName())
				{
					rc = _imageObjectProperties[x];
					break;
				}
			}
		}
	}
	return rc;
}

TiXmlElement *ImageObject::GetImageObjectXml(TiXmlElement *pImageXml)
{
	TiXmlElement *rc = '\0';

	for( TiXmlNode *gchild = pImageXml->FirstChild(); gchild; gchild = gchild->NextSibling() )
	{
		if (gchild->Type() == TiXmlNode::TINYXML_ELEMENT)
		{
			TiXmlElement *imageObjectXml = dynamic_cast<TiXmlElement *>(gchild);
			if (imageObjectXml)
			{
				std::string imageObjectNameXml = imageObjectXml->GetText();
				if (  imageObjectNameXml == GetName())
				{
					rc = imageObjectXml;
					break;
				}
			}
		}
	}
	return rc;
}


//............................................................................................
//protected member functions
//............................................................................................

bool ImageObject::LoadXmlDefinedProperties(TiXmlElement *pImageObjectXml)
{
	bool rc = false;

	if (pImageObjectXml != '\0')
	{
		rc = true;

		ImageProp *pProp = '\0';
		int cnt = GetPropertyCnt();
		for (int x = 0; x < cnt; x++ )
		{
			if ((pProp = GetProperty(x)) != '\0')
			{
				const char *Name = pProp->GetPropName();
				const char *Value = ImageDataset::GetXmlAttribute(pImageObjectXml, Name, pProp->GetPropValue()); 
				if ( SetXmlDefinedProperty(Name, Value) == '\0')
				{
					rc = false;
					break;
				}
			}
		}
	}
	return rc;
}

bool ImageObject::SaveXmlDefinedProperties(TiXmlElement *pImageObjectXml)
{
	bool rc = false;

	if (pImageObjectXml != '\0')
	{
		rc = true;

		ImageProp *pProp = '\0';
		int cnt = GetPropertyCnt();
		for (int x = 0; x < cnt; x++ )
		{
			if ((pProp = GetProperty(x)) != '\0')
			{
				if ( pProp->SaveValueTo(pImageObjectXml) == false)
					rc = false;
			}
			if (rc == false)
				break;
		}
	}
	return rc;
}

bool ImageObject::SetName(const char *timestampStr)
{
	_timestampStr = timestampStr;

	std::stringstream ss;
	ss << _DisplayId << "-" << GetImageObjectType()->GetName() << " (" << GetImageObjectType()->GetBaseClassName() << "): " << _timestampStr;
	_DisplayName = ss.str();

	return true;
}

//............................................................................................
//private member functions
//............................................................................................

bool ImageObject::SetName(int DisplayId)
{
	_DisplayId = DisplayId;

	std::stringstream ss;

	time_t  timestamp;
	time( &timestamp );
	ss <<  timestamp;
	_timestampStr = ss.str();

	ss << DisplayId << "-" << GetImageObjectType()->GetName() << " (" << GetImageObjectType()->GetBaseClassName() << "): " << _timestampStr;
	_DisplayName = ss.str();
	
	return SetName(_timestampStr.c_str());
}

ImageProp *ImageObject::SetXmlDefinedProperty(const char *xmlPropName, const char *xmlPropValue)	//called from Load
{
	ImageProp *rc = '\0';

	if ( (xmlPropName != '\0') && (xmlPropValue != '\0') )
	{
		if((rc = GetProperty(xmlPropName)) != '\0')
			rc->SetPropValue(xmlPropValue);
	}
	return rc;
}

bool ImageObject::CreateImageObjectProperties()
{
	bool rc = false;

	if(_pImageObjectType != '\0')
	{
		int cnt = _pImageObjectType->GetPropertyCnt();
		int x = 0;
		for (x = 0; x < cnt; x++ )
		{
			 ImageTypeProp *pOwnerType = _pImageObjectType->GetProperty(x);
			 if (pOwnerType == '\0')
				break;
			 else
			 {
				 ImageProp *pProp = ImageProp::CreateImageProp(pOwnerType->GetName(), pOwnerType->GetDefaultValue(), pOwnerType);
				 if (pProp == '\0')
					 break;
				 else
					 _imageObjectProperties.push_back(pProp);
			 }
		}
		if (x == cnt)
			rc = true;
	}
	return rc;
}

bool ImageObject::ClearAllImageObjectProperties()
{
	bool rc = false;

	size_t cnt = _imageObjectProperties.size();
	if (cnt > 0 )
	{
		for (size_t x = 0; x < cnt; x++)
			delete _imageObjectProperties[x];
		_imageObjectProperties.clear();
		rc = true;
	}

	return rc;
}

//-------------------------------------------------------------------------------------------------
//			E N D   O F   F I L E
//-------------------------------------------------------------------------------------------------

